package extlib

import (
	"fmt"
	"strconv"

	"math"

	. "git.oschina.net/yangdao/extlib/data_type"
)

type Action func(...interface{})
type Func func(...interface{}) interface{}

func Map(args ...interface{}) ISequence {
	fn := args[0].(func(...interface{}) interface{})
	var loopNum int = math.MaxInt32
	for i := 1; i < len(args); i++ {
		if args[i].(ICollection).Count() < loopNum {
			loopNum = args[i].(ICollection).Count()
		}
	}
	retList := args[1].(ICollection).Empty().(ICollection)
	var curArgArr []interface{} = make([]interface{}, len(args)-1)
	for i := 0; i < loopNum; i++ {
		for j := 1; j < len(args); j++ {
			curArgArr[j-1] = args[j].(IIndexed).Nth(i)
		}
		retList.Conj(fn(curArgArr...))
	}
	return retList.(ISequence)
}
func ForEach(seq interface{}, fn func(v interface{})) {
	iter := seq.(ISequence).GetIterator()
	for iter.MoveNext() {
		fn(iter.Current())
	}
}

func GetMapValue(mapData IAssociative, key interface{}, defaultV ...interface{}) interface{} {
	if len(defaultV) > 0 {
		if mapData.ContainsKey(key) {
			return mapData.Get(key)
		} else {
			return defaultV[0]
		}
	}
	return mapData.Get(key)
}

func ToStr(args ...interface{}) string {
	retStr := ""
	for _, arg := range args {
		switch val := arg.(type) {
		case int64:
			retStr += strconv.Itoa(int(val))
		case int:
			retStr += strconv.Itoa(val)
		case string:
			retStr += val
		case bool:
			if args[0].(bool) == true {
				return "true"
			} else {
				return "false"
			}
		case float32:
			return fmt.Sprint(args[0].(float32))
		case float64:
			return fmt.Sprint(args[0].(float64))
		default:
			panic("ToStr: 不支持的类型")
		}
	}
	return retStr
}

func Str(args ...interface{}) string {
	retStr := ""
	for _, arg := range args {
		switch val := arg.(type) {
		case int64:
			retStr += strconv.Itoa(int(val))
		case int:
			retStr += strconv.Itoa(val)
		case string:
			retStr += val
		case bool:
			if args[0].(bool) == true {
				return "true"
			} else {
				return "false"
			}
		}
	}
	return retStr
}

func Int(arg interface{}) int {
	switch val := arg.(type) {
	case int:
	case string:
		RetInt, err := strconv.Atoi(val)
		if err != nil {
			panic(err)
		}
		return RetInt
	}
	return 0
}

func Float32(arg interface{}) float32 {
	switch val := arg.(type) {
	case int:
		return float32(val)
	case string:
		f, err := strconv.ParseFloat(val, 32)
		if err != nil {
			panic(err)
		}
		return float32(f)
	case float32:
		return val
	case float64:
		return float32(val)
	default:
		panic("不支持的类型")
	}
}

func Filter(fn func(interface{}) bool, seqArg ISequence) ISequence {
	retlst := List()
	iter := seqArg.GetIterator()
	for iter.MoveNext() {
		if fn(iter.Current()) == true {
			retlst.Conj(iter.Current())
		}
	}
	return retlst
}

func Take(number int, seq interface{}) ISequence {
	switch seq.(type) {
	case *TypList:
		retList := List()
		i := 0
		ForEach(seq, func(v interface{}) {
			if i < number {
				retList.AddLast(v)
			}
			i++
		})
		return retList
	case *TypVector:
		vecs := seq.(*TypVector).Buffers[:number]
		return Vector(vecs...)
	default:
		fmt.Println("Take 不支持的类型")
	}
	return nil
}

func Drop(number int, seq interface{}) ISequence {
	switch seq.(type) {
	case *TypList:
		retList := List()
		i := 0
		ForEach(seq, func(v interface{}) {
			if i >= number {
				retList.AddLast(v)
			}
			i++
		})
		return retList
	case *TypVector:
		curVec := seq.(*TypVector)
		vecs := seq.(*TypVector).Buffers[number:curVec.Count()]
		return Vector(vecs...)
	default:
		fmt.Println("Take 不支持的类型")
	}
	return nil
}
